using System;
using System.Collections.Generic;

namespace SmartBoard.Core.Command
{
    public abstract class UIBinderCommandBase:CommandBase, IUIBinderCommand
    {
        #region Private Fields
        private ICommandDescriptor _descriptor;
        private readonly IDictionary<object, Func<object, bool, object>> _widgetsAndCanExecuteCallbackMapping;
        private readonly IDictionary<object, Func<object, ICommandDescriptor, object>> _widgetsAndInitializationCallbackMapping;
        #endregion
        
        #region Ctor

        protected UIBinderCommandBase()
        {
            _widgetsAndInitializationCallbackMapping = new Dictionary<object, Func<object, ICommandDescriptor, object>>();
            _widgetsAndCanExecuteCallbackMapping = new Dictionary<object, Func<object, bool, object>>();
        }
        #endregion

        #region Implementation of IUIBinderCommand

        public ICommandDescriptor Descriptor
        {
            get { return _descriptor; }
            protected set { _descriptor = value; }
        }

        public virtual void SetDescriptor(ICommandDescriptor descriptor)
        {
            _descriptor = descriptor;
            foreach (var initializationCallbackMapping in _widgetsAndInitializationCallbackMapping)
            {
                initializationCallbackMapping.Value(initializationCallbackMapping.Key, _descriptor);
            }
        }

        public void RegisterWidget<TW>(TW widget, Func<TW, ICommandDescriptor, object> initializationCallback, Func<TW, bool, object> canExecuteCallback)
        {
            if (initializationCallback != null)
                initializationCallback(widget, Descriptor);

            if (initializationCallback != null)
                _widgetsAndInitializationCallbackMapping[widget] = (obj, desc) => initializationCallback((TW)obj, desc);

            _widgetsAndCanExecuteCallbackMapping[widget] = (obj, canExecute) => canExecuteCallback((TW)obj, canExecute);
        }

        public void UnRegisterWidget(object widget)
        {
            if (_widgetsAndInitializationCallbackMapping.ContainsKey(widget))
                _widgetsAndInitializationCallbackMapping.Remove(widget);

            if (_widgetsAndCanExecuteCallbackMapping.ContainsKey(widget))
                _widgetsAndCanExecuteCallbackMapping.Remove(widget);
        }
        #endregion

        #region Protected Overrides

        protected override void OnCanExecuteChanged()
        {
            foreach (var canExecuteCallbackMapping in _widgetsAndCanExecuteCallbackMapping)
            {
                canExecuteCallbackMapping.Value(canExecuteCallbackMapping.Key, this.CanExecute);
            }
            base.OnCanExecuteChanged();
        }
        #endregion
    }
}